contents
쿠버네티스(Kubernetes) 는(흔히 K8s로 줄여 부름) 컨테이너화된 애플리케이션의 배포, 확장, 관리를 자동화하는 오픈소스 컨테이너 오케스트레이션 플랫폼입니다. 원래 구글에서 개발했으며, 현재는 CNCF(Cloud Native Computing Foundation)에서 유지보수를 담당하고 있습니다.
쿠버네티스를 마치 여러 서버를 하나의 통일된 컴퓨터처럼 관리하는 클라우드 환경의 운영체제라고 생각할 수 있습니다.
쿠버네티스가 해결하는 문제
쿠버네티스를 이해하려면 먼저 애플리케이션 배포 방식의 진화를 알아야 합니다.
-
전통적인 시대: 애플리케이션을 물리 서버에서 직접 실행했습니다. 애플리케이션을 격리할 방법이 없어 리소스 할당 문제가 발생했습니다(하나의 앱이 모든 리소스를 사용해 다른 앱을 다운시킬 수 있었습니다).
-
가상화 시대: 가상 머신(VM)이 격리 문제를 해결했습니다. 하나의 물리 서버에서 각자 완전한 운영체제를 갖춘 여러 개의 VM을 실행할 수 있었습니다. 하지만 VM은 완전한 OS를 포함하기 때문에 무겁고 오버헤드가 컸습니다.
-
컨테이너 시대: 컨테이너는 경량화된 해결책을 제공합니다. 호스트 OS 커널을 공유하며 프로세스 수준에서 애플리케이션을 격리합니다. 이 덕분에 생성 속도가 빠르고, 이식성이 높으며, 효율적입니다.
하지만 실제 애플리케이션을 위해 수백, 수천 개의 컨테이너를 사용하기 시작하면 새로운 문제에 직면하게 됩니다.
-
다운타임 없이 어떻게 컨테이너의 새 버전을 배포할까?
-
서버가 다운되어 컨테이너가 멈추면 어떻게 해야 할까?
-
트래픽에 따라 컨테이너 수를 어떻게 자동으로 조절할까?
-
서로 다른 컨테이너들이 어떻게 서로를 찾고 통신할까?
이것이 바로 컨테이너 오케스트레이션의 문제이며, 쿠버네티스는 이 문제에 대한 선도적인 해결책입니다.
쿠버네티스 아키텍처: 두뇌와 근육 🧠💪
쿠버네티스 클러스터는 크게 두 부분으로 나뉩니다: 컨트롤 플레인(Control Plane)(두뇌)과 워커 노드(Worker Nodes)(근육)입니다.
비유: 거대한 화물선을 상상해 보세요. 컨트롤 플레인은 선장과 항해사들이 결정을 내리는 '함선의 함교'입니다. 워커 노드는 선원들이 화물을 옮기는(컨테이너를 실행하는) 작업을 수행하는 '화물칸과 엔진실'입니다.
컨트롤 플레인 (두뇌)
컨트롤 플레인의 역할은 클러스터를 관리하는 것입니다. 스케줄링과 같은 전역적인 결정을 내리고, 클러스터 이벤트를 감지하고 대응합니다. 여러 핵심 구성 요소로 이루어져 있습니다.
-
API 서버 (
kube-apiserver): 컨트롤 플레인의 '정문'입니다. 사용자(예:kubectl같은 CLI 도구 사용)나 다른 구성 요소로부터 오는 모든 통신은 API 서버를 통합니다. 요청을 검증하고 처리합니다. -
etcd: 클러스터의 모든 상태를 저장하는 유일한 정보 소스(single source of truth)입니다. 어떤 애플리케이션이 실행 중인지, 복제본은 몇 개인지, 어느 노드에 있는지 등 클러스터의 전체 상태가 저장되는 매우 신뢰성 높은 키-값 저장소입니다.
-
스케줄러 (
kube-scheduler): 새로운 애플리케이션(파드(Pod))을 실행하려고 할 때, 리소스 요구사항, 정책, 제약 조건 등을 바탕으로 적합한 워커 노드를 찾아주는 역할을 합니다. -
컨트롤러 매니저 (
kube-controller-manager): '자동 온도 조절 장치'처럼 작동하는 다양한 '컨트롤러'들을 실행합니다. 각 컨트롤러는 특정 리소스를 담당하며, 클러스터의 상태를 지속적으로 감시하고 현재 상태가 사용자가 정의한 원하는 상태와 일치하도록 작동합니다. 예를 들어, '레플리케이션 컨트롤러'는 항상 정확한 수의 앱 복제본이 실행되도록 보장합니다.
워커 노드 (근육)
워커 노드는 애플리케이션이 실제로 실행되는 머신(VM 또는 물리 서버)입니다. 각 노드는 컨트롤 플레인에 의해 관리되며, 컨테이너를 실행하는 데 필요한 서비스들을 포함합니다.
-
Kubelet (큐블릿): 모든 워커 노드에서 실행되는 에이전트입니다. API 서버와 통신하며, 파드 명세에 정의된 컨테이너들이 해당 노드에서 건강하게 실행되도록 보장합니다.
-
Kube-proxy (큐브 프록시): 각 노드에서 실행되는 네트워크 프록시입니다. 노드의 네트워크 규칙을 유지 관리하여 클러스터 내부 또는 외부에서 파드로의 네트워크 통신을 가능하게 합니다.
-
컨테이너 런타임 (Container Runtime): 컨테이너 실행을 담당하는 소프트웨어입니다. 쿠버네티스는 여러 런타임을 지원하며, 가장 일반적인 것은 containerd이지만 CRI-O 같은 다른 런타임도 사용됩니다. (과거에는 Docker가 많이 사용되었습니다.)
쿠버네티스의 핵심 객체: 빌딩 블록
쿠버네티스에서는 컨테이너를 직접 다루는 대신, 추상적인 "객체(object)"를 다룹니다. 이 객체들은 보통 YAML 파일로 정의하며, 쿠버네티스는 이 객체들을 현실로 만드는 작업을 합니다.
-
파드 (Pod): 쿠버네티스에서 배포할 수 있는 가장 작고 기본적인 단위입니다. 파드는 하나 이상의 밀접하게 연관된 컨테이너들을 감싸는 래퍼(wrapper)입니다. 같은 파드 내의 컨테이너들은 네트워크 공간(IP 주소)과 스토리지 볼륨을 공유할 수 있습니다. 스케줄링과 확장의 기본 단위입니다.
-
디플로이먼트 (Deployment): 애플리케이션의 _원하는 상태_를 기술합니다. "버전 1.2의 웹 서버 복제본 3개를 원한다"고 디플로이먼트에 알려주면, 디플로이먼트가 파드 생성을 관리합니다. 버전 1.3으로 업데이트하고 싶으면 디플로이먼트만 수정하면 됩니다. 그러면 다운타임 없는 롤링 업데이트를 자동으로 처리해 줍니다.
-
서비스 (Service): 파드는 생성되고 소멸되며 IP 주소가 계속 바뀝니다. 서비스는 파드 그룹에 접근할 수 있는 안정적인 단일 엔드포인트(고정 IP 주소와 DNS 이름)를 제공합니다. 내부 로드 밸런서 역할을 하며 트래픽을 건강한 파드들로 분산시킵니다.
-
컨피그맵 (ConfigMap) & 시크릿 (Secret): 애플리케이션 코드로부터 설정을 분리할 수 있게 해주는 객체입니다. 컨피그맵은 민감하지 않은 설정 데이터를 키-값 쌍으로 저장합니다. 시크릿은 비슷하지만 암호나 API 키와 같은 민감한 데이터를 더 안전한 방식으로 저장하는 데 사용됩니다.
-
볼륨 (Volume): 컨테이너의 파일 시스템은 임시적이라 컨테이너가 재시작되면 모든 변경 사항이 사라집니다. 볼륨은 파드에 영속적인 스토리지를 연결하는 방법을 제공하여, 컨테이너가 재시작되어도 데이터가 유지될 수 있도록 합니다.
작동 방식: 간단한 워크플로우
-
컨테이너 이미지와 원하는 복제본 수(예: 3개)를 명시한 디플로이먼트 YAML 파일을 작성합니다.
-
CLI 도구인
kubectl apply -f your-app.yaml명령어로 이 파일을 API 서버에 전송합니다. -
API 서버는 이 설정을 etcd에 기록합니다.
-
컨트롤러 매니저는 새로운 디플로이먼트를 보고, 원하는 상태를 만족시키기 위해 파드 3개를 생성합니다.
-
스케줄러는 아직 노드에 할당되지 않은 3개의 새 파드를 보고, 각 파드에 적합한 워커 노드를 찾아 할당합니다.
-
할당된 각 워커 노드의 Kubelet은 자신에게 새 파드가 할당된 것을 확인하고, 컨테이너 런타임에게 지정된 컨테이너 이미지를 가져와 컨테이너를 실행하라고 지시합니다.
-
미리 정의해 둔 서비스는 레이블을 기반으로 이 새로운 파드들을 자동으로 찾아 트래픽을 보내기 시작합니다.
-
이제 시스템은 원하는 상태에 도달했습니다. 컨트롤러 매니저는 시스템을 지속적으로 모니터링하며, 만약 파드가 다운되면 자동으로 대체 파드를 생성합니다.
쿠버네티스의 장점
-
자가 치유 (Self-Healing): 실패한 컨테이너를 자동으로 재시작하고, 노드가 다운되면 파드를 교체 및 재스케줄링하며, 헬스 체크에 응답하지 않는 컨테이너를 종료시킵니다.
-
자동 확장 (Automatic Scaling): CPU 사용량이나 다른 메트릭에 기반하여 애플리케이션을 자동으로 확장하거나 축소할 수 있습니다.
-
서비스 탐색 및 로드 밸런싱: 애플리케이션에 안정적인 DNS 이름과 IP를 제공하고 트래픽을 분산시킬 수 있습니다.
-
자동화된 롤아웃과 롤백: 다운타임 없이 애플리케이션과 설정 업데이트를 관리합니다. 문제가 발생하면 자동으로 변경 사항을 롤백할 수 있습니다.
-
선언적 모델 (Declarative Model): 원하는 상태("복제본 3개를 원한다")를 선언하면, 쿠버네티스가 "어떻게" 할지를 알아서 처리합니다. 이는 인프라 관리를 훨씬 더 안정적이고 반복 가능하게 만듭니다.
단점
-
복잡성: 쿠버네티스는 학습 곡선이 매우 가파릅니다. 아키텍처와 수많은 객체들은 초보자에게 매우 부담스러울 수 있습니다.
-
운영 오버헤드: 그 자체로 복잡한 시스템이며, 설정, 관리, 문제 해결에 상당한 전문 지식이 필요합니다.
-
만병통치약은 아님: 아주 간단한 단일 컨테이너 애플리케이션에 쿠버네티스를 사용하는 것은 과도한 설계(오버 엔지니어링)일 수 있습니다.
결론적으로, 쿠버네티스는 컨테이너화된 애플리케이션을 대규모로 관리하기 위한 사실상의 표준이 되었으며, 현대적인 클라우드 네이티브 개발을 위한 견고하고 복원력 있는 플랫폼을 제공합니다.
references